package com.gitee.zycra.union.api.common.util;

import lombok.extern.slf4j.Slf4j;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

/**
 * @author zycra
 */
@Slf4j
public final class IPUtil {

    private static final String SPLIT_REGEX = "\\.";

    private static final int MASK = 255;

    private static final int PART_1_LEFT = 24;

    private static final int PART_2_LEFT = 16;

    private static final int PART_3_LEFT = 8;

    private static final int IP_PART_SIZE = 4;

    private static final int PART_2_INDEX = 1;

    private static final int PART_3_INDEX = 2;

    private static final int PART_4_INDEX = 3;

    private IPUtil() {

    }

    /**
     * 获取本机IP地址
     *
     * @return 本机IP地址
     */
    public static InetAddress getLocalHostAddress() {
        try {
            InetAddress candidateAddress = null;
            for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
                NetworkInterface iface = ifaces.nextElement();
                for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
                    InetAddress inetAddr = inetAddrs.nextElement();
                    if (inetAddr.isLoopbackAddress()) {
                        continue;
                    }
                    if (inetAddr.isSiteLocalAddress()) {
                        return inetAddr;
                    }
                    if (candidateAddress == null) {
                        candidateAddress = inetAddr;
                    }
                }
            }
            if (candidateAddress != null) {
                return candidateAddress;
            }
            return InetAddress.getLocalHost();
        } catch (Exception e) {
            log.error("get local host address error", e);
        }
        return null;
    }

    /**
     * IPV4地址转长整型
     *
     * @param ipv4 ipv4地址
     * @return 整型
     */
    public static long ipv4ToLong(String ipv4) {
        if (ipv4 == null) {
            log.error("ipv4 is null");
            return -1L;
        }
        String[] arr = ipv4.split(SPLIT_REGEX);
        if (arr.length != IP_PART_SIZE) {
            log.error("wrong format ipv4");
            return -1L;
        }
        return (Long.parseLong(arr[0]) & MASK) << PART_1_LEFT
                | (Long.parseLong(arr[PART_2_INDEX]) & MASK) << PART_2_LEFT
                | (Long.parseLong(arr[PART_3_INDEX]) & MASK) << PART_3_LEFT
                | Long.parseLong(arr[PART_4_INDEX]) & MASK;
    }

    /**
     * 整型转IPV4地址
     *
     * @param ip 长整型
     * @return IPV4地址
     */
    public static String longToIPV4(long ip) {
        if (ip < 0L) {
            log.error("wrong format ip");
            return null;
        }
        return String.join(".",
                String.valueOf(ip >>> PART_1_LEFT & MASK),
                String.valueOf(ip >>> PART_2_LEFT & MASK),
                String.valueOf(ip >>> PART_3_LEFT & MASK),
                String.valueOf(ip & MASK));
    }
}
